package com.jh.fcsm.service.sys.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jh.fcsm.beans.sys.SysRole;
import com.jh.fcsm.beans.sys.SysRolePermission;
import com.jh.fcsm.beans.sys.SysUserRole;
import com.jh.fcsm.beans.sys.vo.RoleAndRoleTypesVO;
import com.jh.fcsm.beans.sys.vo.SysRoleExportVo;
import com.jh.fcsm.beans.sys.vo.SysRoleVo;
import com.jh.fcsm.common.BaseServiceImpl;
import com.jh.fcsm.common.exception.ServiceException;
import com.jh.fcsm.constant.Constant;
import com.jh.fcsm.dao.sys.SysRoleMapper;
import com.jh.fcsm.dao.sys.SysRolePermissionMapper;
import com.jh.fcsm.dao.sys.SysUserRoleMapper;
import com.jh.fcsm.enums.RoleStatusEnum;
import com.jh.fcsm.service.sys.RoleService;
import com.jh.fcsm.util.AssertUtil;
import com.jh.fcsm.util.security.UUIDUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 角色 controller
 */
@Service
public class RoleServiceImpl extends BaseServiceImpl<SysRoleMapper, SysRole> implements RoleService {

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysRolePermissionMapper sysRolePermissionMapper;

    /**
     * 保存或更新角色
     *
     * @param sysRole 角色
     * @return 结果
     */
    @Override
    @Transactional(readOnly = false)
    public SysRole saveOrUpdateRole(SysRoleVo sysRole) {
        AssertUtil.notNull(sysRole);

        // 校验角色名称和编码不能重复
        if (!checkCodeAndName(sysRole.getRoleCode(), sysRole.getRoleName(), sysRole.getId())) {
            throw new ServiceException("角色名称或角色编码已经存在");
        }

        if (StringUtils.isEmpty(sysRole.getId())) {
            // 新增
            sysRole.setStatus(RoleStatusEnum.ENABLED.getCode());
            sysRole.setStatusTxt(RoleStatusEnum.ENABLED.getValue());
            sysRole.setId(UUIDUtils.getUUID());
            sysRoleMapper.insertSelective(sysRole);
        } else {
            // 更新
            sysRoleMapper.updateByPrimaryKeySelective(sysRole);
        }

        saveRoleMenu(sysRole.getRoleCode(), sysRole.getMenuIds());
        return sysRole;
    }

    /**
     * 保存菜单和角色关联
     *
     * @param roleCode 角色Code
     * @param menus    菜单
     */
    private void saveRoleMenu(String roleCode, List<String> menus) {
        // 清空角色和菜单关联关系
        Example example = new Example(SysRolePermission.class);
        example.createCriteria().andEqualTo("roleCode", roleCode);
        sysRolePermissionMapper.deleteByExample(example);
        if (CollectionUtils.isEmpty(menus)) {
            return;
        }
        List<SysRolePermission> rolePerList = new ArrayList<>();
        for (String menu : menus) {
            SysRolePermission rolePermission = new SysRolePermission();
            rolePermission.setId(UUIDUtils.getUUID());
            rolePermission.setRoleCode(roleCode);
            rolePermission.setResourceId(menu);
            rolePermission.setResourceType("menu");
            rolePerList.add(rolePermission);
        }
        if (!CollectionUtils.isEmpty(rolePerList)) {
            sysRolePermissionMapper.insertList(rolePerList);
        }
    }

    /**
     * 根据角色查询详情
     *
     * @param id 角色Id
     * @return 结果
     */
    @Override
    public SysRoleVo findById(String id) {
        SysRole role = sysRoleMapper.selectByPrimaryKey(id);
        AssertUtil.notNull(role);

        SysRoleVo roleVo = new SysRoleVo();
        BeanUtils.copyProperties(role, roleVo);

        Example example = new Example(SysRolePermission.class);
        example.createCriteria().andEqualTo("roleCode", role.getRoleCode()).andEqualTo("yn", Constant.YES);
        List<SysRolePermission> rolePerList = sysRolePermissionMapper.selectByExample(example);

        if (!CollectionUtils.isEmpty(rolePerList)) {
            List<String> menuList = rolePerList.stream().map(SysRolePermission::getResourceId).collect(Collectors.toList());
            roleVo.setMenuIds(menuList);
        }

        return roleVo;
    }

    /**
     * 判断角色名和角色code是否唯一
     *
     * @param roleCode 角色code
     * @param roleName 角色名
     * @param id       角色ID
     * @return true-角色名和角色code不存在，false-已存在
     */
    private boolean checkCodeAndName(String roleCode, String roleName, String id) {
        int count = sysRoleMapper.countCheckRoleNameOrRoleCode(roleCode, roleName, id);
        // 如果count大于0，则说明角色名或角色code已存在
        return count == 0;
    }

    /**
     * 启用/禁用角色
     *
     * @param roleIds 角色ID
     * @param status  状态 1启用 0禁用
     */
    @Override
    @Transactional(readOnly = false)
    public void changeStatus(String roleIds, Integer status) {
        List<SysRole> roles = sysRoleMapper.selectByIds("'" + roleIds.replace(",", "','") + "'");
        if (!CollectionUtils.isEmpty(roles)) {
            for (SysRole role : roles) {
                SysRole record = new SysRole();
                record.setId(role.getId());
                // 根据状态值获取状态枚举，如果状态值不合法，则默认返回禁用状态的枚举对象
                RoleStatusEnum roleStatusEnum = RoleStatusEnum.getRoleStatusEnum(status);
                record.setStatus(roleStatusEnum.getCode());
                record.setStatusTxt(roleStatusEnum.getValue());
                this.mapper.updateByPrimaryKeySelective(record);
            }
        }
    }
    /**
     * 启用/禁用角色动态验证
     *
     * @param roleIds 角色ID
     * @param status  状态 1启用 0禁用
     */
    @Override
    @Transactional(readOnly = false)
    public void enableDynamicVer(String roleIds, Integer status) {
        List<SysRole> roles = sysRoleMapper.selectByIds("'" + roleIds.replace(",", "','") + "'");
        if (!CollectionUtils.isEmpty(roles)) {
            for (SysRole role : roles) {
                SysRole record = new SysRole();
                record.setId(role.getId());
                // 根据状态值获取状态枚举，如果状态值不合法，则默认返回禁用状态的枚举对象
                RoleStatusEnum roleStatusEnum = RoleStatusEnum.getRoleStatusEnum(status);
                record.setDynamicVer(roleStatusEnum.getCode());
                this.mapper.updateByPrimaryKeySelective(record);
            }
        }
    }


    /**
     * 根据角色查询详情
     *
     * @param roleIds 角色Ids
     */
    @Override
    @Transactional(readOnly = false)
    public void deleteRole(String roleIds) {
        // 删除之前 判断用户是否存在
        if (StringUtils.isBlank(roleIds)) {
            throw new ServiceException("角色id不能为空!");
        }
        String[] ids = roleIds.split(",");
        List<SysUserRole> sysUserRoleList = sysUserRoleMapper.selectUserByRoleIds(ids);
        if (CollectionUtils.isEmpty(sysUserRoleList)) {
            // 逻辑删除
            this.mapper.deleteRoleByIds(ids);
        } else {
            throw new ServiceException("角色下存在用户不允许删除");
        }
    }

    /**
     * 分页查询
     *
     * @param sysRoleVo 角色Vo
     * @return 结果
     */
    @Override
    public PageInfo<RoleAndRoleTypesVO> listPageRoleAndRoleTypeVo(SysRoleVo sysRoleVo) {
        PageHelper.startPage(sysRoleVo.getPageNum(), sysRoleVo.getPageSize());
        List<RoleAndRoleTypesVO> list = this.sysRoleMapper.listRoleAndRoleNameVo(sysRoleVo);
        return new PageInfo<>(list);
    }

    /**
     * 查询当前用户添加的角色列表
     *
     * @param sysRoleVo 角色对象Vo
     * @return 结果
     */
    @Override
    public List<SysRole> listRoleByLoginUser(SysRoleVo sysRoleVo) {
        return sysRoleMapper.listRoleByLoginUser(sysRoleVo);
    }

    /**
     * 导出角色
     *
     * @param sysRoleVo 角色Vo
     * @return 结果
     */
    @Override
    public List<SysRoleExportVo> export(SysRoleVo sysRoleVo) {
        return sysRoleMapper.export(sysRoleVo);
    }

    /**
     * 根据ROLE_CODE返回
     *
     * @param roleCode 角色Code
     * @return 结果
     */
    @Override
    public SysRole findRoleByRoleCode(String roleCode) {
        SysRole role = null;
        if (!StringUtils.isEmpty(roleCode)) {
            Example example = new Example(SysRole.class);
            Criteria criteria = example.createCriteria();
            criteria.andEqualTo("yn", Constant.YES);
            criteria.andEqualTo("roleCode", roleCode);
            List<SysRole> sysRoleList = sysRoleMapper.selectByExample(example);
            if (!CollectionUtils.isEmpty(sysRoleList)) {
                role = sysRoleList.get(0);
            }
        }
        return role;
    }
}
